package com.metering.purchaseServerZuul.filter;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;

import com.metering.purchaseServerCommon.common.bean.constant.CommonConstants;
import com.metering.purchaseServerCommon.common.bean.context.FilterContextHandler;
import com.metering.purchaseServerCommon.common.bean.dto.MenuDTO;
import com.metering.purchaseServerCommon.common.bean.dto.UserToken;
import com.metering.purchaseServerCommon.common.bean.util.JSONUtils;
import com.metering.purchaseServerCommon.common.bean.util.JwtUtils;
import com.metering.purchaseServerCommon.common.bean.util.R;
import com.metering.purchaseServerZuul.pre.admin.MenuService;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;

public class AccessFilter extends ZuulFilter {
	
	private String ignorePath = "/api-admin/login";
	
	@Autowired
	private MenuService menuService;

	@Override
	/**
	 * 是否使用这个过滤器
	 */
	public boolean shouldFilter() {
		// TODO Auto-generated method stub
		return true;
	}

	@Override
	@SuppressWarnings("unused")
	public Object run() throws ZuulException {
		// TODO Auto-generated method stub
		RequestContext requestCtx = RequestContext.getCurrentContext();
		HttpServletRequest request = requestCtx.getRequest();
	    final String requestUri = request.getRequestURI();
        if (isStartWith(requestUri)) {
            return null;
        }
        
        String accessToken = request.getHeader(CommonConstants.CONTEXT_TOKEN);
        if(null == accessToken || accessToken == ""){
            accessToken = request.getParameter(CommonConstants.TOKEN);
        }
        if (null == accessToken) {
            setFailedRequest(R.error401(), 200);
            return null;
        }
        
        try {
			UserToken userToken = JwtUtils.getInfoFromToken(accessToken);
        } catch (Exception e) {
            setFailedRequest(R.error401(), 200);
            return null;
        }
        FilterContextHandler.setToken(accessToken);
        if(!havePermission(request)){
            setFailedRequest(R.error403(), 200);
            return null;
        }
        Set<String> headers = (Set<String>) requestCtx.get("ignoredHeaders");
        //We need our JWT tokens relayed to resource servers
        //添加自己header
//        ctx.addZuulRequestHeader(CommonConstants.CONTEXT_TOKEN, accessToken);
        //移除忽略token
        headers.remove("authorization");
        
		return null;
	}
	
	private void setFailedRequest(Object body, int code) {
        RequestContext ctx = RequestContext.getCurrentContext();
        ctx.setResponseStatusCode(code);
        HttpServletResponse response = ctx.getResponse();
        PrintWriter out = null;
        try{
            out = response.getWriter();
            out.write(JSONUtils.beanToJson(body));
            out.flush();
        }catch(IOException e){
            e.printStackTrace();
        }
        ctx.setSendZuulResponse(false);
    }
	
	private boolean havePermission(HttpServletRequest request){
        String currentURL = request.getRequestURI();
        List<MenuDTO> menuDTOS = menuService.userMenus();
        for(MenuDTO menuDTO:menuDTOS){
            if(currentURL!=null&&null!=menuDTO.getUrl()&&currentURL.startsWith(menuDTO.getUrl())){
                return true;
            }
        }
        return false;
    }

	@Override
	/**
	 * 选择的类型，有四种
	 * pre:这种过滤器在请求被路由之前调用。我们可利用这种过滤器实现身体验证、在集群中选择请求的微服务、记录调试信息等
	 * routing:这种过滤器将请求路由到微服务。这种过滤器用于构建发送给微服务的请求，并使用Apache HttpClient或Netfilx Ribbon请求微服务
	 * POST:这种过滤器在路由到微服务以后执行。这种过滤器可用来为响应添加标准的HTTP Header、收集统计信息和指标、将响应从微服务发送给客户端等。
	 * Error:在其他阶段发生错误时执行该过滤器
	 */
	public String filterType() {
		// TODO Auto-generated method stub
		return "pre";
	}

	@Override
	/**
	 * 执行的顺序，数字越大越靠后
	 */
	public int filterOrder() {
		// TODO Auto-generated method stub
		return 0;
	}
	
	
	/**
	 * 比较请求地址
	 * @Title: isStartWith
	 * @Description: 
	 * @Author GA
	 * @DateTime 2018年12月18日 下午5:40:09
	 * @param requestUri
	 * @return
	 */
	private boolean isStartWith(String requestUri) {
        boolean flag = false;
        for (String s : ignorePath.split(",")) {
            if (requestUri.startsWith(s)) {
                return true;
            }
        }
        return flag;
    }

}
